// VS_BEGIN
#version 330 core
layout (location = 0) in vec3 aPos;

layout (std140) uniform EngineUBO
{
    mat4 u_view;
    mat4 u_project;
    vec3 u_camPos;
};

out vec3 g_texCoord;

uniform mat4 view;
uniform mat4 project;


void main() {
    g_texCoord = aPos;
    gl_Position = project * mat4(mat3(view)) * vec4(aPos, 1.0f);
}
// VS_END

// FS_BEGIN
#version 330 core
layout(location = 0) out vec3 CubeMapDiff;

uniform sampler2D u_irradianceMap;

in vec3 g_texCoord;

out vec4 FragColor;

const float PI = 3.14159265359;


const vec2 invAtan = vec2(0.1591, 0.3183);
vec2 SampleSphericalMap(vec3 v)
{
    vec2 uv = vec2(atan(v.z, v.x), asin(v.y));
    uv *= invAtan;
    uv += 0.5;
    return uv;
}

void main() {

    vec3 normal = normalize(g_texCoord);
    // 卷积获取normal方向上半球光线辐射率总和近似值
    vec3 irradiance = vec3(0.0);

    // IBL漫反射预渲染
    // 在极坐标系上进行半球积分
    // 以Normal为x轴正方向构建极坐标
    vec3 up    = vec3(0.0, 1.0, 0.0);
    vec3 right = normalize(cross(up, normal));
    up         = normalize(cross(normal, right));
    float sampleDelta = 0.05;
    float nrSamples = 0.0; 
    for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta)
    {
        for(float theta = 0.0; theta < 0.5 * PI; theta += sampleDelta)
        {
            // spherical to cartesian (in tangent space)
            vec3 tangentSample = vec3(sin(theta) * cos(phi),  sin(theta) * sin(phi), cos(theta));
            // tangent space to world
            vec3 sampleVec = tangentSample.x * right + tangentSample.y * up + tangentSample.z * normal; 

            irradiance += texture(u_irradianceMap, SampleSphericalMap(sampleVec)).rgb * cos(theta) * sin(theta);
            nrSamples++;
        }
    }
    irradiance = PI * irradiance * (1.0 / float(nrSamples));

    CubeMapDiff = irradiance;
}
// FS_END